//
// Created by Otowa_kotori on 2016/9/25.
//

#include "Game/Game.h"
#include "base.h"
#include "Entities/actor.h"
#include "Entities/plant.h"
#include <algorithm>


namespace skill {
    /*int AbstractAttack::range(){
        const std::string &s = origin->properties["attack_range"];
        try{
            return std::stoi(s);
        }catch(std::exception){
            return -1;
        }
    }*/
    bool AbstractAttack::canUse(Game *g, const std::vector<std::string> &params) {
		if(!CoolDownSkill::canUse(g, params)) return false;
		// 参数个数，这里用小于号是因为衍生的技能可以带更多参数？
        if (params.size() < 1) return false;

		// 双方必须是Actor
		if(!origin->hasPrefix("_Actor_")) return false;
        Entity *target = g->entityManager.findEntityByID(params[0]);
		if(target == nullptr) return false;
		if(!target->hasPrefix("_Actor_")) return false;

		// 判断距离
		Actor *originActor = dynamic_cast<Actor *>(origin);
		Actor *targetActor = dynamic_cast<Actor *>(target);
		if(originActor->squaredDistanceTo(targetActor) > this->range()) return false;

		// 判断参数合法性
		try{
            std::stod(params[1]);
			std::stoi(target->properties["hp"]);
		}catch(std::exception){
			return false;
		}
		return true;
	}
    bool AbstractAttack::use(Game *g, const std::vector<std::string> &params) {
        if (!CoolDownSkill::use(g, params)) return false;
		try{
			Actor *target = dynamic_cast<Actor*>(g->entityManager.findEntityByID(params[0]));
            double damage = std::stod(params[1]);
            (dynamic_cast<Actor*>(origin))->projectDamage(target, damage);
			return true;
		}catch(std::exception){
			return false;
		}
    }

    bool Split::use(Game *g, const std::vector<std::string> &params) {
        if (!CoolDownSkill::use(g, params)) return false;
        int _x = stoi(params[0]), _y = stoi(params[1]);
        entity::BasePlant* p = g->entityManager.get< entity::BasePlant>();
		// Plant *newPlant = g->entityManager.get<BasePlant>();
        p->setPos(Point(_x, _y, 0));
		p->properties["team"] = origin->properties["team"];
        p->properties["energy"] = std::to_string(FixedSplitPower);
        p->useSkill("ReCalculateStats", {});
        int energy = std::stoi(origin->properties["energy"]);
        origin->properties["energy"] = std::to_string(energy - FixedSplitCost);
        return true;
        // return CoolDownSkill::use(g, params);
    }

	bool Split::canUse(Game *g, const std::vector<std::string> &params) {
        if (!CoolDownSkill::canUse(g, params)) return false;
		int _x = stoi(params[0]), _y = stoi(params[1]);
		if (g->entityManager.findActorByPos(Point(_x, _y, 0)) != nullptr)
			return false;
        if (g->terrain.getType(_x, _y) == Terrain::OBSTACLE) return false;
        if (getSquaredEuclideanDist((dynamic_cast<Actor*>(origin))->pos(),Point(_x, _y) ) > SplitRange)
            return false;
        int energy = std::stoi(origin->properties["energy"]);
        if (FixedSplitCost > energy) return false;
		return true;
		// return CoolDownSkill::canUse(g, params);
	}


    bool PlainAttack::canUse(Game *g, const std::vector<std::string> &params) {
        if(!CoolDownSkill::canUse(g, params)) return false;
        // 参数个数，这里用小于号是因为衍生的技能可以带更多参数？
        if (params.size() != 1) return false;

        // 双方必须是Actor
        if(!origin->hasPrefix("_Actor_")) return false;
        Entity *target = g->entityManager.findEntityByID(params[0]);
        if(target == nullptr) return false;
        if(!target->hasPrefix("_Actor_")) return false;

        // 判断距离
        Actor *originActor = dynamic_cast<Actor *>(origin);
        Actor *targetActor = dynamic_cast<Actor *>(target);
        if(originActor->squaredDistanceTo(targetActor) > this->range()) return false;

        // 判断参数合法性
        try{
            std::stoi(target->properties["hp"]);
        }catch(std::exception){
            return false;
        }
        return true;
    }

    bool PlainAttack::use(Game *g, const std::vector<std::string> &params) {
        if (!CoolDownSkill::use(g, params)) return false;
        try{
            Actor* foe = dynamic_cast<Actor*>(g->entityManager.findEntityByID(params[0]));
            (dynamic_cast<Actor*>(origin))->projectDamage(foe, 1);
        }catch(std::exception){
            return false;
        }
    }
}
